#include <fstream>
#include "Game.h"
#include "Defines.h"



Game::Game()
{
	gameOver = false;
	skippedTurn = false;
	x = y = 0;
	xOffset = 10;
	yOffset = 5;
	direction = 0;
	gameStatus = 4;
	MenuInputX = 0;
	MenuInputY = 0;
}


void Game::printTitleScreen()
{
// For now this is commented out, but if we wanted a menu this is where it would go..

	//setcolor(9,0);
	//printf(" __  ___     ___ __  __ ___\n");
	//printf("|__)|__ \\  /|__ |__)/__` | \n");
	//printf("|  \\|___ \\/ |___|  \\.__/_|_\n");
	//setcolor(4,0);
	//printf("         Host Game           \n");
	//printf("         Join Game           \n");
	//printf("       Single Player           \n");

	//gotoxy(MenuInputX,MenuInputY);
	//printf("=>");

	//gotoxy(0,0);
}


void Game::setupBoard()
{
	std::ifstream fin("Misc/Board.txt");
	if(fin.is_open())
	{
		board = new char*[HEIGHT];
		for(int i = 0; i < HEIGHT; ++i)
		{
			board[i] = new char[WIDTH];
			for(int j = 0; j < WIDTH; ++j)
			{
				fin.get(board[i][j]);
			}
			fin.ignore();
		}
	}
}

void Game::drawBoard(dxManager * dxMgr)
{

	
	//printf("(%d, %d)\n", x, y);
	
}

void Game::handleInput(char input)
{
	Player * temp;
	prevX = x;
	prevY = y;

	if(gameStatus == SINGLE && currPlayer == p2)
	{
		p2->populateBoard(board);
		Sleep(1000);
		p2->chooseMove(x, y, input);
	}
	
	if(gameStatus == JOIN && currPlayer == p1)
	{
		tcpNetwork.clintRecvDate(board);
		countPieces();
		temp = currPlayer;
		currPlayer = nextPlayer;
		nextPlayer = temp;
	}else if(gameStatus == HOST && currPlayer == p2)
	{
		tcpNetwork.serverRecvDate(board);
		countPieces();
		temp = currPlayer;
		currPlayer = nextPlayer;
		nextPlayer = temp;
	}else
	{
		switch(input)
		{
		case 'w': y--; break;
		case 'a': x--; break;
		case 's': y++; break;
		case 'd': x++; break;
		case '\r':
			{
				if(board[y][x] == 'g' && legalMove(currPlayer))
				{
					board[y][x] = currPlayer->getSelf();
					currPlayer->addPieces(1);
					temp = currPlayer;
					currPlayer = nextPlayer;
					nextPlayer = temp;
					skippedTurn = false;
				}
			}
			break;
		case 'p':
			{
				if(!anyLegalMovesLeft() && skippedTurn)
				{
					gameOver = true;
				}
				else if(!anyLegalMovesLeft())
				{
					temp = currPlayer;
					currPlayer = nextPlayer;
					nextPlayer = temp;
					skippedTurn = true;
					sendDate();
				}
				else
				{
					//printf("There are still moves for you to make\n");
				}
				
			}
			break;
		}
	}
}

void Game::update()
{

	// collition detection for the coursour not going outside the game board 
	if(x >= WIDTH)
		x = WIDTH - 1;
	else if(x < 0)
		x = 0;

	if(y >= HEIGHT)
		y = HEIGHT - 1;
	else if(y < 0)
		y = 0;
	/////////////////////////////////////////////////////////////////////////

	if(direction)
	{
		if(direction & RIGHT)
		{
			for(int c = x + 1; board[y][c] != currPlayer->getOpp(); ++c)
			{
				board[y][c] = currPlayer->getOpp();
				nextPlayer->addPieces(1);
				currPlayer->addPieces(-1);
			}
		}

		if(direction & UP_RIGHT)
		{
			for(int c = x + 1, r = y - 1; board[r][c] != currPlayer->getOpp(); ++c, --r)
			{
				board[r][c] = currPlayer->getOpp();
				nextPlayer->addPieces(1);
				currPlayer->addPieces(-1);
			}
		}

		if(direction & UP)
		{
			for(int r = y - 1; board[r][x] != currPlayer->getOpp(); --r)
			{
				board[r][x] = currPlayer->getOpp();
				nextPlayer->addPieces(1);
				currPlayer->addPieces(-1);
			}
		}

		if(direction & UP_LEFT)
		{
			for(int c = x - 1, r = y - 1; board[r][c] != currPlayer->getOpp(); --c, --r)
			{
				board[r][c] = currPlayer->getOpp();
				nextPlayer->addPieces(1);
				currPlayer->addPieces(-1);
			}
		}

		if(direction & LEFT)
		{
			for(int c = x - 1; board[y][c] != currPlayer->getOpp(); --c)
			{
				board[y][c] = currPlayer->getOpp();
				nextPlayer->addPieces(1);
				currPlayer->addPieces(-1);
			}
		}

		if(direction & DOWN_LEFT)
		{
			for(int c = x - 1, r = y + 1; board[r][c] != currPlayer->getOpp(); --c, ++r)
			{
				board[r][c] = currPlayer->getOpp();
				nextPlayer->addPieces(1);
				currPlayer->addPieces(-1);
			}
		}

		if(direction & DOWN)
		{
			for(int r = y + 1; board[r][x] != currPlayer->getOpp(); ++r)
			{
				board[r][x] = currPlayer->getOpp();
				nextPlayer->addPieces(1);
				currPlayer->addPieces(-1);
			}
		}

		if(direction & DOWN_RIGHT)
		{
			for(int c = x + 1, r = y + 1; board[r][c] != currPlayer->getOpp(); ++c, ++r)
			{
				board[r][c] = currPlayer->getOpp();
				nextPlayer->addPieces(1);
				currPlayer->addPieces(-1);
			}
		}
		sendDate();

		direction = 0;

	}

	if((p1->getPieces() + p2->getPieces() == 64) || p1->getPieces() == 0 || p2->getPieces() == 0)
	{
		gameOver = true;
	}
}

bool Game::legalMove(Player * p)
{
	if(board[y][x] != 'g')
		return false;
	//determines which directions contain flipable pieces
	//Bits are in this order:
	//Right Up-Right Up Up-Left Left Down-Left Down Down-Right
	direction = 0;

	bool line = false, oppFound = false;

	//Check to the right
	for(int i = x + 1; i < WIDTH; ++i)
	{
		if(board[y][i] == 'g')
		{
			line = false;
			break;
		}
		else if(board[y][i] == p->getSelf() && oppFound)
		{
			line = true;
			break;
		}
		else if(board[y][i] == p->getOpp() && (i + 1) < WIDTH)
		{
			oppFound = true;
		}
		else
			break;
	}

	if(line)
		direction |= RIGHT;

	oppFound = false;
	line = false;

	//Check to the left
	for(int i = x - 1; i >= 0; --i)
	{
		if(board[y][i] == 'g')
		{
			line = false;
			break;
		}
		else if(board[y][i] == p->getSelf() && oppFound)
		{
			line = true;
			break;
		}
		else if(board[y][i] == p->getOpp() && (i - 1) >= 0)
		{
			oppFound = true;
		}
		else
			break;
	}

	if(line)
		direction |= LEFT;

	oppFound = false;
	line = false;

	//Check above
	for(int i = y - 1; i >= 0; --i)
	{
		if(board[i][x] == 'g')
		{
			line = false;
			break;
		}
		else if(board[i][x] == p->getSelf() && oppFound)
		{
			line = true;
			break;
		}
		else if(board[i][x] == p->getOpp() && (i - 1) >= 0)
		{
			oppFound = true;
		}
		else
			break;
	}

	if(line)
		direction |= UP;

	oppFound = false;
	line = false;

	//Check below
	for(int i = y + 1; i < HEIGHT; ++i)
	{
		if(board[i][x] == 'g')
		{
			line = false;
			break;
		}
		else if(board[i][x] == p->getSelf() && oppFound)
		{
			line = true;
			break;
		}
		else if(board[i][x] == p->getOpp() && (i + 1) < HEIGHT)
		{
			oppFound = true;
		}
		else
			break;
	}

	if(line)
		direction |= DOWN;

	oppFound = false;
	line = false;

	//Check below and to the right
	for(int i = y + 1, j = x + 1; i < HEIGHT && j < WIDTH; ++i, ++j)
	{
		if(board[i][j] == 'g')
		{
			line = false;
			break;
		}
		else if(board[i][j] == p->getSelf() && oppFound)
		{
			line = true;
			break;
		}
		else if(board[i][j] == p->getOpp() && (i + 1) < HEIGHT && (j + 1) < WIDTH)
		{
			oppFound = true;
		}
		else
			break;
	}

	if(line)
		direction |= DOWN_RIGHT;

	oppFound = false;
	line = false;

	//Check below and to the left
	for(int i = y + 1, j = x - 1; i < HEIGHT && j > 0; ++i, --j)
	{
		if(board[i][j] == 'g')
		{
			line = false;
			break;
		}
		else if(board[i][j] == p->getSelf() && oppFound)
		{
			line = true;
			break;
		}
		else if(board[i][j] == p->getOpp() && (i + 1) < HEIGHT && (j - 1) > 0)
		{
			oppFound = true;
		}
		else
			break;
	}

	if(line)
		direction |= DOWN_LEFT;

	oppFound = false;
	line = false;

	//Check up and to the right
	for(int i = y - 1, j = x + 1; i > 0 && j < WIDTH; --i, ++j)
	{
		if(board[i][j] == 'g')
		{
			line = false;
			break;
		}
		else if(board[i][j] == p->getSelf() && oppFound)
		{
			line = true;
			break;
		}
		else if(board[i][j] == p->getOpp() && (i - 1) > 0 && (j + 1) < WIDTH)
		{
			oppFound = true;
		}
		else
			break;
	}

	if(line)
		direction |= UP_RIGHT;

	oppFound = false;
	line = false;

	//Check up and to the left
	for(int i = y - 1, j = x - 1; i > 0 && j > 0; --i, --j)
	{
		if(board[i][j] == 'g')
		{
			line = false;
			break;
		}
		else if(board[i][j] == p->getSelf() && oppFound)
		{
			line = true;
			break;
		}
		else if(board[i][j] == p->getOpp() && (i - 1) > 0 && (j - 1) > 0)
		{
			oppFound = true;
		}
		else
			break;
	}

	if(line)
		direction |= UP_LEFT;

	oppFound = false;
	line = false;
	
	if(direction)
		return true;

	return false;
}

void Game::setupPlayers()
{
	p1 = new Player('b', 'w');

	if(gameStatus == SINGLE)
	{
		p2 = new AI('w', 'b');
		p2->createArray();
	}
	else
	{
		p2 = new Player('w', 'b');
	}
	currPlayer = p1;
	nextPlayer = p2;
	gameStatus = SINGLE;
}

void Game::setupHost()
{
	setupPlayers();
	tcpNetwork.setUpNetworkServer();
	gameStatus = HOST;
}

void Game::setupJoin(char * IPinput)
{
	setupPlayers();
	tcpNetwork.setUpNetworkClint(IPinput);
	gameStatus = JOIN;
}

void Game::sendDate()
{
	if(gameStatus == JOIN)
	{
		tcpNetwork.clintSendDate(board);
	}
	if(gameStatus == HOST)
	{
		tcpNetwork.serverSendDate(board);
	}
}

bool Game::anyLegalMovesLeft()
{
	for(int row = 0; row < HEIGHT; ++row)
	{
		for(int col = 0; col < WIDTH; ++col)
		{
			if(legalMove(currPlayer, row, col))
			{
				return true;
			}
		}
	}

	return false;
}

bool Game::legalMove(Player * p, int row, int col)
{
	if(board[row][col] != 'g')
	{
		return false;
	}

	bool line = false, oppFound = false;

	//Check to the right
	for(int i = col + 1; i < WIDTH; ++i)
	{
		if(board[row][i] == 'g')
		{
			line = false;
			break;
		}
		else if(board[row][i] == p->getSelf() && oppFound)
		{
			return true;
		}
		else if(board[row][i] == p->getOpp() && (i + 1) < WIDTH)
		{
			oppFound = true;
		}
		else
			break;
	}

	oppFound = false;
	line = false;

	//Check to the left
	for(int i = col - 1; i >= 0; --i)
	{
		if(board[row][i] == 'g')
		{
			line = false;
			break;
		}
		else if(board[row][i] == p->getSelf() && oppFound)
		{
			return true;
		}
		else if(board[row][i] == p->getOpp() && (i - 1) >= 0)
		{
			oppFound = true;
		}
		else
			break;
	}

	oppFound = false;
	line = false;

	//Check above
	for(int i = row - 1; i >= 0; --i)
	{
		if(board[i][col] == 'g')
		{
			line = false;
			break;
		}
		else if(board[i][col] == p->getSelf() && oppFound)
		{
			return true;
		}
		else if(board[i][col] == p->getOpp() && (i - 1) >= 0)
		{
			oppFound = true;
		}
		else
			break;
	}

	oppFound = false;
	line = false;

	//Check below
	for(int i = row + 1; i < HEIGHT; ++i)
	{
		if(board[i][col] == 'g')
		{
			line = false;
			break;
		}
		else if(board[i][col] == p->getSelf() && oppFound)
		{
			return true;
		}
		else if(board[i][col] == p->getOpp() && (i + 1) < HEIGHT)
		{
			oppFound = true;
		}
		else
			break;
	}

	oppFound = false;
	line = false;

	//Check below and to the right
	for(int i = row + 1, j = col + 1; i < HEIGHT && j < WIDTH; ++i, ++j)
	{
		if(board[i][j] == 'g')
		{
			line = false;
			break;
		}
		else if(board[i][j] == p->getSelf() && oppFound)
		{
			return true;
		}
		else if(board[i][j] == p->getOpp() && (i + 1) < HEIGHT && (j + 1) < WIDTH)
		{
			oppFound = true;
		}
		else
			break;
	}

	oppFound = false;
	line = false;

	//Check below and to the left
	for(int i = row + 1, j = col - 1; i < HEIGHT && j > 0; ++i, --j)
	{
		if(board[i][j] == 'g')
		{
			line = false;
			break;
		}
		else if(board[i][j] == p->getSelf() && oppFound)
		{
			return true;
		}
		else if(board[i][j] == p->getOpp() && (i + 1) < HEIGHT && (j - 1) > 0)
		{
			oppFound = true;
		}
		else
			break;
	}

	oppFound = false;
	line = false;

	//Check up and to the right
	for(int i = row - 1, j = col + 1; i > 0 && j < WIDTH; --i, ++j)
	{
		if(board[i][j] == 'g')
		{
			line = false;
			break;
		}
		else if(board[i][j] == p->getSelf() && oppFound)
		{
			return true;
		}
		else if(board[i][j] == p->getOpp() && (i - 1) > 0 && (j + 1) < WIDTH)
		{
			oppFound = true;
		}
		else
			break;
	}

	oppFound = false;
	line = false;

	//Check up and to the left
	for(int i = row - 1, j = col - 1; i > 0 && j > 0; --i, --j)
	{
		if(board[i][j] == 'g')
		{
			line = false;
			break;
		}
		else if(board[i][j] == p->getSelf() && oppFound)
		{
			return true;
		}
		else if(board[i][j] == p->getOpp() && (i - 1) > 0 && (j - 1) > 0)
		{
			oppFound = true;
		}
		else
			break;
	}

	oppFound = false;
	line = false;

	return false;
}

void Game::countPieces()
{
	int numWhite = 0, numBlack = 0;

	for(int row = 0; row < HEIGHT; ++row)
	{
		for(int col = 0; col < WIDTH; ++col)
		{
			if(board[row][col] == 'b')
				++numBlack;
			else if(board[row][col] == 'w')
				++numWhite;
		}
	}
	p1->setPieces(numBlack);
	p2->setPieces(numWhite);
}